package com.lzw.tool.tree;

import lombok.Getter;

import java.util.*;
import java.util.function.Function;

/**
 * 子节点反找所有父节点
 *
 * @param <T> 对象
 * @param <R> 父子关系判断字段类型
 */
@Getter
public class ParentRelationShip<T, R> {

    Map<R, ResourceNode<T>> map;

    private Function<T, R> functionParent;

    private Function<T, R> functionChildren;

    /**
     * 默认Parent字段为 <b>null</b> 是根节点
     * @param functionParent 父节点id字段
     * @param functionChildren 当前节点id字段
     */
    public ParentRelationShip(Function<T, R> functionParent, Function<T, R> functionChildren) {
        this.functionParent = functionParent;
        this.functionChildren = functionChildren;
    }

    public Map<R, ResourceNode<T>> createRelation(List<T> sources) {
        if (map != map){
            return map;
        }
        final int size = sources.size();
        map = new HashMap<>(size);
        for (T node : sources) {
            final R apply = functionChildren.apply(node);
            final ResourceNode resourceNode = new ResourceNode(node);
            map.put(apply, resourceNode);
        }
        buildRelation();
        return map;
    }

    /**
     * 建立关系结构
     */
    public void buildRelation() {
        final Set<Map.Entry<R, ResourceNode<T>>> entries = map.entrySet();
        for (Map.Entry<R, ResourceNode<T>> item : entries) {
            final ResourceNode<T> value = item.getValue();
            final ResourceNode<T> pNode = Optional.ofNullable(value)
                    .map(ResourceNode::getData)
                    .map(functionParent)
                    .map(map::get)
                    .orElse(ResourceNode.EMPTY_NODE);
            if (pNode != ResourceNode.EMPTY_NODE) {
                value.setParentNode(pNode);
            }
        }
    }
}
